var utils = {

    /**
    * Check given data and returns true if an Array is introduced
    * @param any data
    * @return {boolean}
    */
    isArray: function (obj) {
        return (typeof obj === "object") && (obj instanceof Array);
    },

    /**
    * Check given data and returns true if a String is introduced
    * @param any data
    * @return {boolean}
    */
    isString: function (str) {
        return typeof (str) === "string";
    },

    /**
    * Check given data and returns true if a Function is introduced
    * @param any data
    * @return {boolean}
    */
    isFunction: function (func) {
        return typeof (func) === "function";
    },


    /**
    * Check given data and returns true if a Number is introduced
    * @param any data
    * @return {boolean}
    */
    isNumber: function (numb) {
        return typeof (numb) === "number";
    },

    /**
     * Sort given array by provided rule in comparator function
     * @param {Array} list
     * @param {Function} comparator
     */
    sort: function (list, comparator) {
        if (!this.isArray(list) || list.length === 0) {
            throw new Error("You need to put array for use method utils.sort");
        }
        if (!this.isFunction(comparator)) {
            comparator = function (a, b) {
                return a - b;
            };
        }

        return list.sort(comparator);
    },

    /**
     * Make first letter of given string upper case
     * @param {String} string
     * @return {String} capitalized string
     */

    capitalize: function (str) {
        if (!this.isString(str) || str.length === 0) {
            throw new Error("You need to put string for use method utils.capitalize");
        }

        return _.str.capitalize(str);
    },

    /**
     * Camelize given string or array of string
     * @param {Array|String} sequence
     * @return {String} capitalized string
     */

    camelize: function (sequence) {

        if (!(this.isArray(sequence) || this.isString(sequence)) || sequence.length === 0) {
            throw new Error("You need to put a string or array of strings to use method utils.camelize");
        }

        return _.str.camelize(sequence);
    },

    /**
     * Cut of any count of spaces from the beginning and from the end of the string
     * @param {String} str
     * @return {String}
     */

    trim: function (str) {
        if (!this.isString(str) || str.length === 0) {
            throw new Error("You need to give string to use utils.trim");
        }
        return _.str.trim(str, " ");
    },

    /**
     *  Change each list"s element by applying handler
     *  @params {Array|Object} list - input sequence
     *  @params {Function} iterator  - some rule which changes each element
     *  @return {Array} new list with changes elements
     */

    map: function (list, iterator) {
        if (!this.isFunction(iterator)) {
            throw new Error ("interator should be Function");
        }

        return _.map(list, iterator);
    },

    /**
     * Group some input sequence of element by some rule
     * @param {Array} list - input sequence
     * @param {Function} iterator -  provide group id for each element
     * @return {Object} object of group id properties which point to arrays of element from input sequence
     */

    groupBy: function (list, iterator) {
        if (!this.isArray(list) || list.length === 0) {
            throw new Error("You need to put array for use method utils.groupBy");
        }
        if (!this.isFunction(iterator)) {
            throw new Error("You need to put func for use method utils.groupBy or put more arguments in the function");
        }

        return _.groupBy(list, iterator);
    }
};
